﻿

using AspectInjector.Broker;
using DryIoc;
using Microsoft.Extensions.Configuration;
using Minotaur.App.Core;
using Minotaur.App.Core.Attributes;
using Minotaur.App.Core.Exceptions;
using Minotaur.App.Core.Interceptors;
using Minotaur.App.Core.Redis;
using Minotaur.App.Domains.Model.SystemLog;
using Minotaur.App.ViewModels;
using Minotaur.App.Views;
using Newtonsoft.Json;
using Prism.DryIoc;
using Prism.Ioc;
using Prism.Modularity;
using ServiceStack.Script;
using SqlSugar;
using System;
using System.IO;
using System.Linq;
using System.Net;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Xml.Linq;
[assembly: log4net.Config.XmlConfigurator(ConfigFile = "App.config", ConfigFileExtension = "config", Watch = true)]
namespace Minotaur.App
{
    /// <summary>
    /// Interaction logic for App.xaml
    /// </summary>
    public partial class App
    {
        private SqlSugarScope sqlSugarScope;
        public static log4net.ILog operationLog = log4net.LogManager.GetLogger("OperationLog");
        public static log4net.ILog errorLog = log4net.LogManager.GetLogger("ErrorLog");
        protected override Window CreateShell()
        {
            return Container.Resolve<LogIn>();
        }
        private IConfiguration configuration;
        protected override void RegisterTypes(IContainerRegistry containerRegistry)
        {
            this.RegisterGlobaConfigTypes(containerRegistry);
            this.RegisterLogicServiceTypes(containerRegistry);
            this.RegisterLogicRepositoryTypes(containerRegistry);
            //this.RegisterInterceptor(containerRegistry);
        }
        protected override void OnStartup(StartupEventArgs e)
        {
            var builder = new ConfigurationBuilder()
                          .SetBasePath(Directory.GetCurrentDirectory())
                          .AddJsonFile("Config/database.json", optional: false, reloadOnChange: true)
                          .AddJsonFile("Config/assemblys.json", optional: false, reloadOnChange: true)
                          .AddJsonFile("Config/crypto.json", optional: false, reloadOnChange: true);
            configuration = builder.Build();
            ConnectionConfig config = configuration.Get<GlobalConfigModel>()?.ConnectionConfig;
            sqlSugarScope = new SqlSugarScope(config);
            //UI线程未捕获异常处理事件
            this.DispatcherUnhandledException += App_DispatcherUnhandledException;
            //Task线程内未捕获异常处理事件
            TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException;
            //非UI线程未捕获异常处理事件
            AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
            base.OnStartup(e);
        }
        /// <summary>
        /// 非UI线程未捕获异常处理事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        /// <exception cref="NotImplementedException"></exception>
        private void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
        {
            if (e.ExceptionObject != null && e.ExceptionObject != null && e.ExceptionObject is GlobalException)
            {
                this.InitException(e.ExceptionObject as GlobalException);
            }
            errorLog.Error(e.ExceptionObject);
            HandyControl.Controls.Growl.Error("系统错误,请联系管理员！");
        }

        /// <summary>
        /// Task线程内未捕获异常处理事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        /// <exception cref="System.NotImplementedException"></exception>
        private void TaskScheduler_UnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs e)
        {
            if (e.Exception != null && e.Exception.InnerException != null && e.Exception.InnerException is GlobalException)
            {
                this.InitException(e.Exception.InnerException as GlobalException);
            }
            errorLog.Error(e.Exception.InnerException is null ? e.Exception : e.Exception.InnerException);
            e.SetObserved();
        }
        /// <summary>
        /// 获取本地IP地址信息
        /// </summary>
        string GetAddressIP()
        {
            ///获取本地的IP地址
            string AddressIP = string.Empty;
            foreach (IPAddress _IPAddress in Dns.GetHostEntry(Dns.GetHostName()).AddressList)
            {
                if (_IPAddress.AddressFamily.ToString() == "InterNetwork")
                {
                    AddressIP = _IPAddress.ToString();
                }
            }
            return AddressIP;
        }
        private void InitException(GlobalException globalException)
        {
            if (globalException is null) return;
            var _userModel = globalException.GlobalUserModel;
            if (_userModel is null) return;
            SystemRequestLog systemRequestLog = new SystemRequestLog()
            {
                Account = _userModel?.Account,
                CNName = _userModel?.EmpName,
                Code = _userModel?.TenementCode,
                CreatDate = DateTime.Now,
                Creator = _userModel?.EmpId,
                EmpCode = _userModel?.EmpCode,
                EmpId = _userModel?.EmpId,
                ENName = _userModel?.EmpName,
                ExecuteCompletiontime = DateTime.Now,
                ExecuteDate = DateTime.Now,
                ExecuteMethod = globalException.MethodName,
                ExecuteParameter = JsonConvert.SerializeObject(globalException.Paramter),
                IPAddress = GetAddressIP(),
                Language = 0,
                LogType = 0,
                ExecuteResult = globalException?.Message,
                ExecuteClass = globalException.Type?.FullName,
                PositionId = _userModel?.PositionId,
                ModifDate = DateTime.Now,
                Modifier = _userModel?.EmpId,
                OrgId = _userModel?.OrgId,
                OrgName = _userModel?.OrgName,
                Phone = "",
                PositionName = _userModel?.PositionName,
                TCnname = _userModel?.TenementName,
                UserAgent = "Windows desktop",
                RequestParamtetr = JsonConvert.SerializeObject(globalException.Paramter),
            };
            sqlSugarScope.Insertable<SystemRequestLog>(systemRequestLog).ExecuteCommand();
        }

        /// <summary>
        /// UI线程未捕获异常处理事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        /// <exception cref="System.NotImplementedException"></exception>
        private void App_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
        {
            e.Handled = true;
            if (e.Exception != null)
            {
                if (e.Exception.InnerException != null && e.Exception.InnerException is GlobalException)
                    this.InitException(e.Exception.InnerException as GlobalException);
                else
                    this.InitException(e.Exception as GlobalException);
            } 
            errorLog.Error(e.Exception.InnerException is null ? e.Exception : e.Exception.InnerException);
            HandyControl.Controls.Growl.Error("系统错误,请联系管理员！");
        }

        /// <summary>
        /// 注册全局配置数据
        /// </summary>
        /// <param name="containerRegistry"></param>
        protected void RegisterGlobaConfigTypes(IContainerRegistry containerRegistry)
        {
            containerRegistry.RegisterSingleton<ModuleCatalogManager>();
            containerRegistry.RegisterSingleton<IConfiguration>(() => configuration);
            containerRegistry.RegisterSingleton<IRedisClient, RedisClient>();
            containerRegistry.RegisterSingleton<SqlSugarScope>(() => sqlSugarScope);
        }

        /// <summary>
        /// 配置逻辑层
        /// </summary>
        /// <param name="containerRegistry"></param>
        protected void RegisterLogicServiceTypes(IContainerRegistry containerRegistry)
        {
            string[] serviceAssembys = configuration.Get<GlobalConfigModel>()?.ServiceAssemblys;
            foreach (var item in serviceAssembys)
            {
                Assembly assemblies = Assembly.Load(item);
                if (assemblies != null)
                {
                    var reflections = assemblies.GetTypes()
                     .Where(o => typeof(ICommonInterface).IsAssignableFrom(o))
                     .Where(t => t.IsInterface);
                    foreach (var type in reflections)
                    {
                        var refleClass = assemblies.GetTypes()
                          .Where(t => type.IsAssignableFrom(t)).
                          Where(t => t.IsClass);
                        if (refleClass.Any())
                        {
                            foreach (var cls in refleClass)
                            {
                                containerRegistry.Register(type, cls);
                            }
                        }
                    }
                }
            }
        }

        /// <summary>
        /// 配置数据库访问层
        /// </summary>
        /// <param name="containerRegistry"></param>
        protected void RegisterLogicRepositoryTypes(IContainerRegistry containerRegistry)
        {
            string[] serviceAssembys = configuration.Get<GlobalConfigModel>()?.RepositoryAssemblys;
            foreach (var item in serviceAssembys)
            {
                Assembly assemblies = Assembly.Load(item);
                if (assemblies != null)
                {
                    var reflections = assemblies.GetTypes()
                     .Where(o => typeof(ICommonInterface).IsAssignableFrom(o))
                     .Where(t => t.IsInterface);
                    foreach (var type in reflections)
                    {
                        var refleClass = assemblies.GetTypes()
                          .Where(t => type.IsAssignableFrom(t)).
                          Where(t => t.IsClass);
                        if (refleClass.Any())
                        {
                            foreach (var cls in refleClass)
                            {
                                containerRegistry.Register(type, cls);
                            }
                        }
                    }
                }
            }
        }

        /// <summary>
        /// 配置AOP拦截
        /// </summary>
        /// <param name="containerRegistry"></param>
        protected void RegisterInterceptor(IContainerRegistry containerRegistry)
        {
            Assembly assemblies = Assembly.Load("Minotaur.App.Core");
            if (assemblies != null)
            {
                var reflections = assemblies.GetTypes()
                 .Where(o => typeof(ICommonInterceptor).IsAssignableFrom(o))
                 .Where(t => t.IsInterface);
                foreach (var type in reflections)
                {
                    var refleClass = assemblies.GetTypes()
                      .Where(t => type.IsAssignableFrom(t)).
                      Where(t => t.IsClass);
                    if (refleClass.Any())
                    {
                        foreach (var cls in refleClass)
                        {
                            containerRegistry.Register(type, cls);
                        }
                    }
                }
            }
        }
    }
}
